package org.testis.gui.mvc.controller.testdesign;

import org.testis.gui.mvc.controller.*;
import org.testis.gui.mvc.model.testdesign.SearchModel;
import org.testis.gui.mvc.view.testdesign.SearchView;
import org.testis.orm.labelhandler.ILabelContainer;
import org.testis.orm.labelhandler.LabelFilterDataHandler;
import org.testis.orm.labelhandler.LabelFilterRefined;
import org.testis.orm.labelhandler.LabelHandlerFactory;
import org.testis.orm.labelhandler.LabelUtils;
import org.testis.utils.tree.MyDefaultMutableTreeNode;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.testis.orm.classes.T_label_filters;
import org.testis.orm.refinedclasses.DesignPart;
import org.testis.orm.refinedclasses.TestDesignTreeNode;

/**
 *
 * @author Cahit Emir Erel
 */
public class SearchController extends AbstractController {

    public static final String ERROR_PROPERTY = "LastError";
    public static final String COPY = "Copy";
    public static final String CLONE = "Clone";
    public static final String ONE_TO_ONE_COPY = "1-to-1Copy";
    public static final String NO_OPERATION = "NoOperation";
    public static final String TREE_LOAD = "LoadTree";
    public static final String TREE_REFRESH = "RefreshTree";
    public static final String SELECT_DESIGN_PART = "SelectedNode";
    public static final String SHOW_SELECTER = "ShowSelecter";
    public static final String PROPERTIES = "Properties";
    public static final String MARK_AS_SELECTED = "Mark";
    public static final String MARK_AS_UNSELECTED = "UnMark";
    public static final String SELECT_OPERATION = "Operation";
    public static final String APPLY_SELECTION = "Apply";
    public static final String LABEL_FILTER_LIST_PROPERTY = "LabelFilterList";
    private MyDefaultMutableTreeNode m_original;

    public SearchController() {
        super();
    }

    public void operationApplySelection(boolean selected) {
        setModelProperty(APPLY_SELECTION, selected);
    }

    private Boolean getApplySelection() {
        return (Boolean) getModelProperty(APPLY_SELECTION);
    }

    public void operationChangeProperties(String properties) {
        setModelProperty(PROPERTIES, properties);
    }

    public void operationClickOk() {
        MyDefaultMutableTreeNode tree = getTree();
        if (getApplySelection()) {
            synchronizeTrees(tree, m_original);
        }
        /*
        String operation = getOperation();
        TestDesignTreeNode testTree = TestDesignControllerList.newInstance().getTreeController().constructTree(tree, null);
        if (operation.equals(COPY)) {
        TestDesignControllerList.newInstance().getPopupController().operationSetObject(new MyDefaultMutableTreeNode(testTree, true),
        "Paste (Copy Selection)");
        } else if (operation.equals(CLONE)) {
        TestDesignControllerList.newInstance().getPopupController().operationSetObject(new MyDefaultMutableTreeNode(testTree, true),
        "Paste (Clone Selection)");
        } else if (operation.equals(ONE_TO_ONE_COPY)) {
        TestDesignControllerList.newInstance().getPopupController().operationSetObject(new MyDefaultMutableTreeNode(testTree, true),
        "Paste (1-to-1 Copy Selection)");
        } else if (operation.equals(NO_OPERATION)) {
        return;
        }
         */
    }

    private void synchronizeTrees(MyDefaultMutableTreeNode src,
            MyDefaultMutableTreeNode dst) {
        dst.setSelected(src.isSelected());
        dst.setSelectedSingle(src.isSelected());
        for (int i = 0; i < src.getChildCount(); i++) {
            synchronizeTrees(src.getChildAt(i), dst.getChildAt(i));
        }
    }

    public void operationCloseWindow() {
        cleanAll();
    }

    public void selectOperation(String operation) {
        if (operation != null) {
            setModelProperty(SELECT_OPERATION, operation);
        }
    }

    private String getLabelsAsStr(MyDefaultMutableTreeNode node) {
        TestDesignTreeNode tNode = (TestDesignTreeNode) node.getUserObject();
        String result = LabelHandlerFactory.getInstance(
                tNode).getLabelsAsStr(tNode, true);
        return result;
    }

    private void execRegexRecursive(MyDefaultMutableTreeNode node, String regex) {
        TestDesignTreeNode tdtNode = (TestDesignTreeNode) node.getUserObject();
        DesignPart dp = tdtNode.getObject();
        if (dp != null && dp instanceof ILabelContainer) {
            String labelsAsStr = getLabelsAsStr(node);
            boolean isSelected = LabelUtils.matchesLabelPattern(regex,
                    labelsAsStr);
            node.setSelected(isSelected);
            if (isSelected) {
                node.setSelectedSingle(isSelected);
            }
        }
        for (int i = 0; i < node.getChildCount(); i++) {
            execRegexRecursive(node.getChildAt(i), regex);
        }
    }

    public void operationExecRegex(String regex) {
        execRegexRecursive(getTree(), regex);
        operationRefreshTree();
    }

    /*private void operationMarkNodeAsSelected(MyDefaultMutableTreeNode node) {
    setModelProperty(MARK_AS_SELECTED, node);
    }

    private void operationMarkNodeAsUnSelected(MyDefaultMutableTreeNode node) {
    setModelProperty(MARK_AS_UNSELECTED, node);
    }*/
    private void initialize() {
        addModel(new SearchModel());
        SearchView view = new SearchView(TestDesignControllerList.newInstance().
                getParentFrame(),
                true);
        view.pack();
        addView(view);
    }

    public void operationRefreshTree() {
        setModelProperty(TREE_REFRESH, true);
    }

    synchronized public void operationLoadTree(MyDefaultMutableTreeNode tree) {
        setModelProperty(TREE_LOAD, tree);
    }

    synchronized public void operationSelectDesignPart(
            MyDefaultMutableTreeNode node) {
        if (node != null && node.getUserObject() != null) {
            setModelProperty(SELECT_DESIGN_PART, node);
            operationChangeProperties(node.getUserObject().toString());
        }
    }

    private MyDefaultMutableTreeNode getTree() {
        return (MyDefaultMutableTreeNode) getModelProperty(TREE_LOAD);
    }

    public void startTestDesignSelecter(MyDefaultMutableTreeNode node) {
        initialize();
        m_original = node;
        operationLoadTree(
                new MyDefaultMutableTreeNode(
                m_original.getUserObject(), true));
        operationLoadLabelFilters();
        setModelProperty(SHOW_SELECTER, true);
    }

    public MyDefaultMutableTreeNode getSelectedMutableTreeNode() {
        return (MyDefaultMutableTreeNode) getModelProperty(SELECT_DESIGN_PART);
    }

    public void operationLoadLabelFilters() {
        LinkedList<LabelFilterRefined> filterList = getLabelFilters();
        setModelProperty(LABEL_FILTER_LIST_PROPERTY, filterList);
    }

    private LinkedList<LabelFilterRefined> getLabelFilters() {
        LinkedList<LabelFilterRefined> result = new LinkedList<LabelFilterRefined>();
        LabelFilterDataHandler handler = new LabelFilterDataHandler();
        List<T_label_filters> filterList = handler.getLabelFilterList();
        for (Iterator<T_label_filters> it = filterList.iterator(); it.hasNext();) {
            T_label_filters filter = it.next();
            result.add(new LabelFilterRefined(filter));
        }
        return result;
    }

    public void operationAddLabelFilter(String name, String filterExpression) {
        LabelFilterDataHandler handler = new LabelFilterDataHandler();
        if (handler.addLabelFilter(name, filterExpression) != 0) {
            operationLoadLabelFilters();
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to add label fiter...");
        }
    }

    public void operationUpdateLabelFilter(int id, String name,
            String expression) {
        LabelFilterDataHandler handler = new LabelFilterDataHandler();
        if (handler.saveLabelFilter(id, name, expression)) {
            operationLoadLabelFilters();
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to add label fiter...");
        }
    }
}
